package org.frog.sgs.character;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.mina.core.session.IoSession;
import org.frog.sgs.card.basic.Basic;
import org.frog.sgs.card.equipment.Equipment;
import org.frog.sgs.card.general.General;
import org.frog.sgs.card.general.GeneralEventDispatcher;
import org.frog.sgs.card.role.Role;
import org.frog.sgs.card.scheme.type.JudgeType;
import org.frog.sgs.card.strength.Strength;
import org.frog.sgs.card.strength.StrengthFactory;
import org.frog.sgs.event.SgsEventCode;
import org.frog.sgs.io.SgsMsg;
import org.frog.sgs.server.game.ServerCardManager;
import org.frog.sgs.server.game.ServerInstance;
import org.frog.sgs.server.game.status.ServerStatus;
import org.frog.sgs.server.msg.ServerMsgBroadcast;
import org.frog.sgs.server.msg.ServerMsgGenerals;
import org.frog.sgs.server.msg.ServerMsgSyncAllCharacterInfo;
import org.frog.sgs.server.msg.ServerMsgSyncCharacterInfo;

/**
 * 角色（身份+将领+体力+基本牌）
 * 
 * @author duanxiangqi
 * @date 2012-10-15
 */
@SuppressWarnings("unchecked")
public class Character implements Serializable {

	private static final long serialVersionUID = -91475521920497959L;

	private Role role;

	private General general;

	private Strength strength;

	private IoSession session;

	private int position;

	private ServerInstance instance;

	private boolean die;

	// 手牌 id：card
	private Map<Integer, Basic> cardsInHand = new TreeMap<Integer, Basic>();

	// 装备区 position：card
	private Map<Integer, Equipment> equipments = new TreeMap<Integer, Equipment>();

	// 判定区 保证顺序 LinkedHashMap type:card
	private Map<JudgeType, Basic> judgeSchemes = new LinkedHashMap<JudgeType, Basic>();

	private Map<Object, Object> attributes = new HashMap<Object, Object>();

	private int currentEventCode = SgsEventCode.WAITING;

	public void init() {
		currentEventCode = SgsEventCode.WAITING;
	}

	/**
	 * 处理事件
	 * 
	 * @param msg
	 * @throws Exception
	 */
	public void processMsg(SgsMsg msg) throws Exception {
		int code = msg.getCode();
		if (code == SgsEventCode.CHOOSE_GENERAL_OVER) {
			chooseGeneralOver(msg);
		} else {
			GeneralEventDispatcher.instance.dispatch(general, msg);
		}
	}

	/**
	 * 选择将领
	 */
	public void sendChooseGenerals() {
		if (instance.getStatus() != ServerStatus.allocateGeneral) {
			System.err.println("游戏当前状态是" + instance.getStatus() + "，操作失败");
			return;
		}
		if (this == instance.getCharacterManager().getZhuGong()) {
			List<General> tempGenerals = instance.getCardManager().getOutZhuGongRandomGeneral();
			setAttribute("tempGenerals", tempGenerals);
			setCurrentEventCode(SgsEventCode.CHOOSE_GENERAL_OVER);
			sendMsg(new ServerMsgGenerals(tempGenerals));
			String msg = "等待主公" + getViewName() + "选择将领";
			sendMsgToOther(new ServerMsgBroadcast(msg));
		} else {
			int size = instance.getCharacterManager().getCharacters().size();
			List<General> tempGenerals = instance.getCardManager().getOutRandomGenerals(size < 9 ? 3 : 2);
			setAttribute("tempGenerals", tempGenerals);
			setCurrentEventCode(SgsEventCode.CHOOSE_GENERAL_OVER);
			sendMsg(new ServerMsgGenerals(tempGenerals));
		}
	}

	/**
	 * 客户端选择将领完毕
	 * 
	 * @param msg
	 * @throws Exception
	 */
	public void chooseGeneralOver(SgsMsg msg) throws Exception {
		int generalId = 0;
		if (msg == null) {
			// 默认值
			List<General> tempGenerals = (List<General>) getAttribute("tempGenerals");
			generalId = tempGenerals.get(0).getId();
		} else {
			generalId = msg.readInt();
		}
		List<General> tempGenerals = (List<General>) getAttribute("tempGenerals");
		for (General general : tempGenerals) {
			if (general.getId() == generalId) {
				setGeneral(general);
				general.setCharacter(this);
				setCurrentEventCode(SgsEventCode.WAITING);
			} else {
				instance.getCardManager().addGeneral(general);
			}
		}
		if (general == null) {
			System.err.println("非法操作:无效的将领ID " + generalId);
			session.close(true);
		}
		int maxStrength = general.getMaxStrength();

		if (this == instance.getCharacterManager().getZhuGong()) {
			maxStrength++;
			sendMsgToAll(new ServerMsgBroadcast("主公选择了将领：" + general.getViewName()));
			List<Character> characters = instance.getCharacterManager().getCharacters();
			sendMsg(new ServerMsgBroadcast("等待其他玩家选择将领"));
			for (Character character : characters) {
				if (character != this) {
					character.sendChooseGenerals();
				}
			}
		} else {
			sendMsg(new ServerMsgBroadcast("您选择了将领： " + general.getViewName()));
		}
		Strength strength = StrengthFactory.instance.newInstance(maxStrength);
		setStrength(strength);
		strength.setCharacter(this);
		List<Character> characters = instance.getCharacterManager().getCharacters();
		for (Character character : characters) {
			// 将领选择完毕
			if (character.getSession() != null && character.getGeneral() == null) {
				return;
			}
		}
		// 从主公开始按顺序分发基础牌
		Character zhugong = instance.getCharacterManager().getZhuGong();
		zhugong.getInitCards();
		Character next = zhugong;
		while ((next = next.getNextAlive()) != zhugong) {
			next.getInitCards();
		}
		for (Character character : characters) {
			character.syncAllCharacterInfo();
		}
		// 主公回合开始
		String value = "游戏开始！";
		sendMsgToAll(new ServerMsgBroadcast(value));
		zhugong.getGeneral().triggerEvent(SgsEventCode.MY_ROUND_INIT);
	}

	/**
	 * 获取初始4张牌
	 */
	public void getInitCards() {
		ServerCardManager cardManager = instance.getCardManager();
		List<Basic> basics = cardManager.getOutBasics(4);
		String msg = "您获得了4张手牌：";
		for (Basic basic : basics) {
			basic.setCharacter(this);
			cardsInHand.put(basic.getId(), basic);
			msg += basic.getViewName() + ")；";
		}
		sendMsg(new ServerMsgBroadcast(msg));
	}

	/**
	 * 同步所有玩家将领、体力等信息到客户端
	 */
	public void syncAllCharacterInfo() {
		System.out.println(getViewName() + "：同步所有玩家信息");
		sendMsg(new ServerMsgSyncAllCharacterInfo(instance.getCharacterManager().getCharacters()));
	}

	/**
	 * 同步玩家将领、体力、牌等信息到客户端
	 */
	public void syncCharacterInfo() {
		System.out.println(getViewName() + "：同步个人信息");
		System.out.println("您的身份是：\t" + role.getViewName() + " " + general.getViewName());
		System.out.println("您当前的体力是：\t" + strength.getViewName());
		System.out.println("您当前的手牌是：\t");
		for (Basic card : cardsInHand.values()) {
			System.out.println("\t" + card.getViewName());
		}
		System.out.println("您当前的装备是：");
		for (Equipment card : equipments.values()) {
			System.out.println("\t" + card.getViewName());
		}
		System.out.println("您当前的判定牌是：");
		for (JudgeType type : judgeSchemes.keySet()) {
			System.out.println("\t" + type.getName() + "：" + judgeSchemes.get(type).getViewName());
		}
		sendMsg(new ServerMsgSyncCharacterInfo(this));
	}

	/**
	 * 获取下一个没死亡的玩家
	 * 
	 * @return
	 */
	public Character getNextAlive() {
		List<Character> characters = instance.getCharacterManager().getCharacters();
		int size = characters.size();
		int nextPosition = this.position != size - 1 ? (this.position + 1) : 0;
		Character next = instance.getCharacterManager().getByPosition(nextPosition);
		return next.isDie() ? next.getNextAlive() : next;
	}

	/**
	 * 获取上一个没死亡的玩家
	 * 
	 * @return
	 */
	public Character getPreviousAlive() {
		List<Character> characters = instance.getCharacterManager().getCharacters();
		int size = characters.size();
		int previousPosition = this.position == 0 ? (size - 1) : (this.position - 1);
		Character previous = instance.getCharacterManager().getByPosition(previousPosition);
		return previous.isDie() ? previous.getPreviousAlive() : previous;
	}

	/**
	 * 是否在线
	 * 
	 * @return
	 */
	public boolean isOnline() {
		return session != null;
	}

	public void destory() {
		try {
			session.close(false);
		} catch (Exception e) {}
	}

	/**
	 * 广播一个提示消息
	 * 
	 * @param msg
	 */
	public void broadcast(String msg) {
		sendMsgToAll(new ServerMsgBroadcast(getViewName() + "：" + msg));
	}

	/**
	 * 发送个人消息
	 * 
	 * @param msg
	 */
	public void sendMsg(SgsMsg msg) {
		if (session != null) {
			session.write(msg);
		}
	}

	/**
	 * 发送消息给其他人
	 * 
	 * @param msg
	 */
	public void sendMsgToOther(SgsMsg msg) {
		List<Character> characters = instance.getCharacterManager().getCharacters();
		for (Character character : characters) {
			if (character != this) {
				character.sendMsg(msg);
			}
		}
	}

	/**
	 * 发送消息给全部人
	 * 
	 * @param msg
	 */
	public void sendMsgToAll(SgsMsg msg) {
		instance.getCharacterManager().sendMsgToAll(msg);
	}

	/**
	 * 判定区是否有牌
	 * 
	 * @return
	 */
	public boolean hasJudgeCard() {
		return !judgeSchemes.isEmpty();
	}

	/**
	 * 判定区是否有指定类型的判定
	 * 
	 * @return
	 */
	public boolean hasJudge(JudgeType judgeType) {
		return judgeSchemes.containsKey(judgeType);
	}

	/**
	 * 往判定区添加一个判定牌 保证顺序 先进后出 添加到最后面
	 * 
	 * @param judgeType
	 * @param basic
	 * @return
	 */
	public boolean addJudge(JudgeType judgeType, Basic basic) {
		if (hasJudge(judgeType)) {
			return false;
		}
		judgeSchemes.put(judgeType, basic);
		return true;
	}

	/**
	 * 获取下一个需要判定的类型 保证顺序 先进后出 从第一个开始取
	 * 
	 * @return
	 */
	public JudgeType getNextJudgeType() {
		if (!hasJudgeCard()) {
			return null;
		}
		Iterator<JudgeType> iterator = judgeSchemes.keySet().iterator();
		JudgeType next = null;
		while (iterator.hasNext()) {
			next = iterator.next();
		}
		return next;
	}

	public Basic getNextJudge() {
		if (!hasJudgeCard()) {
			return null;
		}
		Iterator<Basic> iterator = judgeSchemes.values().iterator();
		Basic next = null;
		while (iterator.hasNext()) {
			next = iterator.next();
		}
		return next;
	}

	/**
	 * 删除一个判定牌，返回删除后的判定牌
	 * 
	 * @param judgeType
	 * @return
	 */
	public Basic removeJudge(JudgeType judgeType) {
		return judgeSchemes.remove(judgeType);
	}

	/**
	 * 是否有指定类型的手牌
	 */
	public boolean hasCardInHand(Class<? extends Basic> clazz) {
		for (Basic basic : cardsInHand.values()) {
			if (basic.getClass() == clazz) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 根据ID获取手牌
	 * 
	 * @param id
	 * @return
	 */
	public Basic getCardInHandById(int id) {
		for (Basic basic : cardsInHand.values()) {
			if (basic.getId() == id) {
				return basic;
			}
		}
		return null;
	}

	/**
	 * 删除一张牌手牌
	 */
	public Basic removeCardInHandById(int id) {
		return cardsInHand.remove(id);
	}

	/**
	 * 是否有指定类型的装备
	 */
	public boolean hasEquipment(int position) {
		return equipments.containsKey(position);
	}

	/**
	 * 根据部位获取装备
	 * 
	 * @param position
	 * @return
	 */
	public Equipment getEquipmentByPosition(int position) {
		return equipments.get(position);
	}

	/**
	 * 删除一个装备
	 */
	public Equipment removeEquipmentByPosition(int position) {
		return equipments.remove(position);
	}

	public String getViewName() {
		return "[玩家" + position + ":" + (role == null ? "未知" : role.getViewName()) + "]";
	}

	public void setAttribute(Object key, Object value) {
		attributes.put(key, value);
	}

	public Object getAttribute(Object key) {
		return attributes.get(key);
	}

	public void removeAttribute(Object key) {
		attributes.remove(key);
	}

	public Map<Object, Object> getAttributes() {
		return attributes;
	}

	public void setAttributes(Map<Object, Object> attributes) {
		this.attributes = attributes;
	}

	public Role getRole() {
		return role;
	}

	public void setRole(Role role) {
		this.role = role;
	}

	public General getGeneral() {
		return general;
	}

	public void setGeneral(General general) {
		this.general = general;
	}

	public Strength getStrength() {
		return strength;
	}

	public void setStrength(Strength strength) {
		this.strength = strength;
	}

	public IoSession getSession() {
		return session;
	}

	public void setSession(IoSession session) {
		this.session = session;
	}

	public int getPosition() {
		return position;
	}

	public void setPosition(int position) {
		this.position = position;
	}

	public String toString() {
		return getViewName();
	}

	public int getCurrentEventCode() {
		return currentEventCode;
	}

	public void setCurrentEventCode(int currentEventCode) {
		this.currentEventCode = currentEventCode;
	}

	public ServerInstance getInstance() {
		return instance;
	}

	public void setInstance(ServerInstance instance) {
		this.instance = instance;
	}

	public Map<Integer, Basic> getCardsInHand() {
		return cardsInHand;
	}

	public void setCardsInHand(Map<Integer, Basic> cardsInHand) {
		this.cardsInHand = cardsInHand;
	}

	public Map<Integer, Equipment> getEquipments() {
		return equipments;
	}

	public void setEquipments(Map<Integer, Equipment> equipments) {
		this.equipments = equipments;
	}

	public Map<JudgeType, Basic> getJudgeSchemes() {
		return judgeSchemes;
	}

	public void setJudgeSchemes(Map<JudgeType, Basic> judgeSchemes) {
		this.judgeSchemes = judgeSchemes;
	}

	public void setDie(boolean die) {
		this.die = die;
	}

	public boolean isDie() {
		return this.die;
	}
}
